/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package noyau;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 *
 * @author Hoang
 */
public class LiaisonServeur implements Runnable{
    private final boolean MAPMode = true; 
    private String adresse;
    private int port;
    private Socket sock;
    private DataInputStream in;
    private DataOutputStream out;
    private LiaisonCapteur liaisonCapteur;
    private JTextField textAdresse;
    private JTextField textPort;
    private JTextField textNbCap;
    private JTextArea textMsg;
    private JTextArea textMsgCap;
    private Thread t;
    private JButton bouton;

    /**
     * Créer une instance de LiaisonServeur avec les paramètres de connexion.
     * !Attention, ce constructeur n'initialise pas la connexion.
     * @param adresseServeur : adresse du serveur GHOME
     * @param portServer : port du serveur GHOME
     */
    public LiaisonServeur(String adresseServeur, int portServer) {
        this.adresse = adresseServeur;
        this.port = portServer;
    }

    /**
     * Créer une instance de LiaisonServeur avec les paramètres de connexion
     * et les contrôle d'IHM
     * !Attention, ce constructeur n'initialise pas la connexion.
     * @param adresse
     * @param port
     * @param textAdresse
     * @param textPort
     * @param textNbCap
     * @param textMsg 
     */
    public LiaisonServeur(String adresse, int port, JTextField textAdresse, 
            JTextField textPort, JTextField textNbCap, JTextArea textMsg, 
            JTextArea textMsgCap, JButton bouton ) {
        this.adresse = adresse;
        this.port = port;
        this.textAdresse = textAdresse;
        this.textPort = textPort;
        this.textNbCap = textNbCap;
        this.textMsg = textMsg;
        this.textMsgCap = textMsgCap;
        this.bouton = bouton;
    }
    
    /**
     * Tâche de communication avec le serveur
     */
    public void run(){
        boolean exit = false;
        try {
            //Phase init
            String param = "";
            
            //Ouverture de la connexion et initialisation des flux
            sock = new Socket(adresse, port);
            in = new DataInputStream(sock.getInputStream());
            out = new DataOutputStream(sock.getOutputStream());
            this.bouton.setEnabled(false);
            
            //Lecture et analyse des paramètres
            byte[] buff = new byte[200];
            int ok  = in.read(buff);
            param = LiaisonCapteur.byteArrayToHexString(buff);
            ParseParam(param);
            
            //Phase moteur
            while(!exit){
                try{
                    byte[] buff2 = new byte[200];
                    int ok2  = in.read(buff2);
                    String line = LiaisonCapteur.byteArrayToHexString(buff2).trim();
                    
                    //Perte de connexion
                    if(line.equals("")){
                        this.textMsg.append("Perte de connexion.\r\n");
                        if(t.isAlive())
                            t.interrupt();
                        this.bouton.setEnabled(true);
                        exit = true;
                    }
                        
                    if(this.MAPMode)
                    {
                        this.textMsg.append("MSG Reçu :" + line + "\r\n");
                    }
                    TraiterMsg(line);
                } catch (IOException e) {
                    //PERTE DE CONNEXION
                    this.textMsg.append("Impossible de recevoir le message "
                            + "du serveur" + "\r\n");
                    this.textMsg.append("Perte de connexion.\r\n");
                    if(t.isAlive())
                        t.interrupt();
                    this.bouton.setEnabled(true);
                    exit = true;
                }
            }
            
        } catch (UnknownHostException ex) {
            //SERVEUR INTROUVABLE
            //Logger.getLogger(LiaisonServeur.class.getName()).log(Level.SEVERE, null, ex);
            if(t.isAlive())
                t.interrupt();
            this.bouton.setEnabled(true);
            System.exit(-1);
        } catch (IOException ex) {
            this.textMsg.append("Serveur introuvable.\r\n");
        }
        this.textMsg.append("Déconnecter du serveur\r\n");
    }    
    
    public void ParseParam(String msg) {
        int i = 3;
        String[] tokens = msg.split("[$]");
        ArrayList<Capteur> listeCap = new ArrayList<Capteur>();
        
        this.textAdresse.setText(tokens[1]);
        this.textPort.setText(tokens[2]);
        
        int nbCapteur = Integer.parseInt(tokens[3]);
        
        for (i = 4; i<(nbCapteur*2+4); i=i+2) {
            Capteur c = new Capteur(tokens[i]);
            int typeCap = Integer.parseInt(tokens[i+1]);
            switch (typeCap) {
                case 1: c.setType(Capteur.TYPE.CAP_TEMP_EN);
                    listeCap.add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 2: c.setType(Capteur.TYPE.CAP_LUMIERE_EN);
                    listeCap.add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 3: c.setType(Capteur.TYPE.CAP_PRESENT_EN);
                    listeCap.add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 4: c.setType(Capteur.TYPE.CAP_TEMP_SUN);
                    listeCap.add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 5: c.setType(Capteur.TYPE.CAP_LUMIERE_SUN);
                    listeCap.add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 6: c.setType(Capteur.TYPE.CAP_PRESENT_SUN);
                    listeCap.add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 8: c.setType(Capteur.TYPE.CAP_LUM_PRE_EN);
                    listeCap.add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 9: c.setType(Capteur.TYPE.CAP_CONTACT_EN);
                    listeCap.add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 10:c.setType(Capteur.TYPE.CAP_BOUTON_EN);
                    listeCap.add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                default: this.textMsg.append("PARSING ERROR : TYPE CAPTEUR INCONNU\r\n");
            }            
        }
        int nbAct = Integer.parseInt(tokens[i]);
        for (int j =i+1; j<(nbAct*2+i); j=j+2) {
            Capteur c = new Capteur(tokens[j]);
            int typeCap = Integer.parseInt(tokens[j+1]);
            if (typeCap == 7){
                c.setType(Capteur.TYPE.ACT_INT_EN);
                listeCap.add(c);
                this.textMsg.append("Actionneur " + c.getId() + " ajouté\r\n");
            } else
                this.textMsg.append("PARSING ERROR : TYPE CAPTEUR INCONNU\r\n");
        }
        
        this.textNbCap.setText(String.valueOf(listeCap.size()));
        liaisonCapteur = new LiaisonCapteur(listeCap,tokens[1],
                Integer.parseInt(tokens[2]), this.textMsgCap, this.out);
        t = new Thread(liaisonCapteur);
        t.start();
    }
    
    public void TraiterMsg(String msg){
        String[] tokens = msg.split("[$]");
        if (tokens[0].equals("3")){
            boolean verif = false;
            List<Capteur> temp = Collections.synchronizedList(liaisonCapteur.getListeCapteurs());
            synchronized (temp){
                Iterator<Capteur> c = temp.iterator();
                while (c.hasNext()) {
                    Capteur cap = c.next();
                    if (cap.getId().equals(tokens[1])){
                        verif = true;
                        if (tokens[2].equals("1")){
                            liaisonCapteur.AllumerLumiere(tokens[1]);
                            textMsg.append("Actionneur " + cap.getId() + " allumé\r\n");
                            
                        }
                        else {
                            liaisonCapteur.EteindreLumiere(tokens[1]);
                            textMsg.append("Actionneur " + cap.getId() + " éteint\r\n");
                        }
                    }
                }
            }
            if(!verif){
                textMsg.append("Aucun actionneur avec l'ID " + tokens[1]);
            }
        }
        if (tokens[0].equals("4")){
            Capteur c = new Capteur(tokens[1]);
            int typeCap = Integer.parseInt(tokens[2]);
            switch (typeCap)
            {
                case 1: c.setType(Capteur.TYPE.CAP_TEMP_EN);
                    liaisonCapteur.getListeCapteurs().add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 2: c.setType(Capteur.TYPE.CAP_LUMIERE_EN);
                    liaisonCapteur.getListeCapteurs().add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 3: c.setType(Capteur.TYPE.CAP_PRESENT_EN);
                    liaisonCapteur.getListeCapteurs().add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 4: c.setType(Capteur.TYPE.CAP_TEMP_SUN);
                    liaisonCapteur.getListeCapteurs().add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 5: c.setType(Capteur.TYPE.CAP_LUMIERE_SUN);
                    liaisonCapteur.getListeCapteurs().add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 6: c.setType(Capteur.TYPE.CAP_PRESENT_SUN);
                    liaisonCapteur.getListeCapteurs().add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 7:c.setType(Capteur.TYPE.ACT_INT_EN);
                    liaisonCapteur.getListeCapteurs().add(c);
                    this.textMsg.append("Actionneur " + c.getId() + " ajouté\r\n");
                    break;
                case 8: c.setType(Capteur.TYPE.CAP_LUM_PRE_EN);
                    liaisonCapteur.getListeCapteurs().add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 9: c.setType(Capteur.TYPE.CAP_CONTACT_EN);
                    liaisonCapteur.getListeCapteurs().add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                case 10: c.setType(Capteur.TYPE.CAP_BOUTON_EN);
                    liaisonCapteur.getListeCapteurs().add(c);
                    this.textMsg.append("Capteur " + c.getId() + " ajouté\r\n");
                    break;
                default: 
                    this.textMsg.append("ERREUR : TYPE DE CAPTEUR INVALIDE\r\n");
            }
            this.textNbCap.setText(String.valueOf(this.liaisonCapteur.getListeCapteurs().size()));
        }
        if (tokens[0].equals("5")){
                boolean verif = liaisonCapteur.EnleverCapteur(tokens[1]);
                if(verif){
                    this.textMsg.append("Capteur/Actionneur " + tokens[1] + " enlevé\r\n");
                    this.textNbCap.setText(String.valueOf(this.liaisonCapteur.getListeCapteurs().size()));
                } else
                    this.textMsg.append("ID introuvable - Aucun capteur/actionneur enlevé\r\n");
        }
    }
}


